<?php

/*
2012年11月23日
模板引擎类
	朱贺
2012年1月24日增加伪静态处理。
2014年6月10日更新到新核心。
*/

class Template{
	
	var $template;
	var $tpl;
	var $tpl_ROOT;
	var $cache_ROOT;
	
	function __construct($siteid) //构造函数
    {
		global $_G;
		$this->tpl_ROOT = APP_ROOT.'/'.$_G['config']['output']['template'].($siteid?$siteid.'/':'');		
		$this->cache_ROOT = APP_ROOT.'/'.$_G['config']['cache']['dir'].'site/'.($siteid?$siteid.'/':'').(defined('userWeb')?userWeb:'');
		$this->template='';
    }
	function Template_class()
	{
		$this->__construct();
	}
	
	function inc(){
		$Pattern = "/<!--#include file=\"([\s\S]*?)\"-->/";
		if(preg_match($Pattern,$this->template,$matches))
		{
			//$includes = explode('../',$matches[1]);
			$this->template = str_replace($matches[0] , @file_get_contents($this->tpl_ROOT.dirname($this->tpl).'/'.$matches[1]) ,$this->template);
		}
		if(preg_match_all($Pattern, $this->template,$temp)!=false) $this->inc();	
	}
	
	function parse_my(){ //自定义标签
		$Pattern = "/{My:([\s\S]*?)}/";
		$this->template = $this->template;
	}
	
	function parse_sys(){ // 系统标签
		$this->template = preg_replace("/\{Sys:([\s\S]*?)\}/","<?php echo \\1; ?>",$this->template);
	}
	
	function parse_field(){
		
	}
	
	//注意自定义SQL语句的处理
	//加强组合SQL的多表查询处理
	function parse_com(){ // 列表标签
		$Pattern = '/<!--(.+?):\{(.+?)\}-->([\s\S]*?)<!--\\1-->/';		
		$this->template = preg_replace($Pattern, "<?php
\$psize = intval(\$_GET['psize']);		
\$limit_\\1 = empty(\$psize)?GetLimit@\\2@:\$psize;

\$page_\\1 = intval(\$_GET['page']);			
\$page_\\1 = page@\\2@?(empty(\$page_\\1) ? 1 : \$page_\\1):1;
\$start = page@\\2@?(\$page_\\1-1)*\$limit_\\1:GetStart@\\2@;		
if(\$start<0) \$start = 0;
\$sql = getsql@\\2@;
\$ArrOrder = OrderArr@\\2@;
\$count_\\1 = C::t('public_list')->fetch_all_by_sql(\$sql, \$ArrOrder, 0, 0 , 1);

if(\$count_\\1){
	\$Arr_\\1 = C::t('public_list')->fetch_all_by_sql(\$sql, \$ArrOrder, \$start, \$limit_\\1 , 0);
	foreach(\$Arr_\\1 as \$k=>\$\\1){
	?>\\3<?php
	}
	if(page@\\2@) \$pages = multi(\$count_\\1, \$limit_\\1, \$page_\\1, \$mpurl);
}
?>",$this->template);
		if(preg_match_all($Pattern, $this->template,$temp)!=false) $this->parse_com();
	}
	
	//替换SQL语句
	function parse_sql(){

		if(preg_match('/getsql@(.+?)@/', $this->template, $Msql)){
					
			$sql = $this->GetAttr($Msql[1],'sql',FALSE);			
			$Array = $this->GetAttr($Msql[1],'array',FALSE);			
			$order = $this->GetAttr($Msql[1],'order',FALSE);
			
			$limit = $this->GetAttr($Msql[1],'row',FALSE);
			$start = $this->GetAttr($Msql[1],'start',FALSE);
			$page = $this->GetAttr($Msql[1],'page',FALSE);
			if($page) $page = 1;
			else $page = 0;
			$limit = intval($limit);
			$limit = empty($limit) ? 0:$limit;
			
			$start = intval($start);
			$start = $start?$start:0;
			
			if($order) $order = ' order by '.$order;
			//if($limit) $limitstr = '.DB::limit($start, '.$limit.')';	
			//else $limitstr = '.DB::limit($start, $limit)';			
			if($Array) $Array = 'array('.$Array.')';
			else $Array= 'array()';
			
			
			$this->template = str_replace('GetLimit@'.$Msql[1].'@', $limit, $this->template);
			$this->template = str_replace('GetStart@'.$Msql[1].'@', $start, $this->template);
			$this->template = str_replace($Msql[0] , '"'.$sql.'"', $this->template);
			$this->template = str_replace('OrderArr@'.$Msql[1].'@', $Array , $this->template);
			$this->template = str_replace('page@'.$Msql[1].'@', $page , $this->template);
			
			
			//$this->template = str_replace($Msql[0], '"'.$sql.$order.'"'.$limitstr.$Array, $this->template);
		}
		if(preg_match_all('/getsql@(.+?)@/', $this->template,$temp)!=false) $this->parse_sql();			
	}
	
	//提取标签条件
	function GetAttr($Tagsstr,$AttrName,$ReplaceSpace = false){
		$str="";
		$Pattern = '/\$' .$AttrName . '=(.+?) \$/';
		preg_match($Pattern,$Tagsstr." $",$Matches);
		if($Matches){
			$str = $Matches[1];
		}
		if($ReplaceSpace){
			$str = str_replace(" ","",$str);
		}
		//$str = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/","\".\\1.\"",$str);
		//$str = preg_replace("/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/","\".\\1.\"",$str);
		//$str = preg_replace("/\{(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/","\".\\1.\"",$str);
		//$str = preg_replace("/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", "\".\\1.\"",$str);
		return $str = str_replace("}",".\"",str_replace("{","\".",$str));
	}

	// 判断标签主要以替换为主
	function parse_if(){ // 执行判断
		$this->template = preg_replace("/\{if\s+(.+?)\}/","<?php if(\\1) { ?>",$this->template);
		$this->template = preg_replace("/\{else\}/","<?php } else { ?>",$this->template);
		$this->template = preg_replace("/\{elseif\s+(.+?)\}/","<?php } elseif (\\1) { ?>",$this->template);
		$this->template = preg_replace("/\{\/if\}/","<?php } ?>",$this->template);
		$this->template = $this->template;
	}
	
	function parse_echo(){
		$this->template = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/","<?php echo \\1;?>",$this->template);
		$this->template = preg_replace("/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/","<?php echo \\1;?>",$this->template);
		$this->template = preg_replace("/\{(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/","<?php echo \\1;?>",$this->template);
		$this->template = preg_replace("/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", "<?php echo \\1;?>",$this->template);
	}

	function parse(){
		//制作缓存文件
		$this->template = '<?php if(!defined(\'IN_SING\')) {exit(\'Access Denied\');}?>'."\n".$this->template;
                
		if(!is_file($this->cache_ROOT.$this->tpl.".cache.php")){                    
			$this->run();                        
			$this->write_cache($this->template, $this->tpl);
			@chmod($this->cache_ROOT.$this->tpl.".cache.php", 0777);
		}else {
			$a=filemtime($this->cache_ROOT.$this->tpl.".cache.php"); // 获取缓存文件时间
			//缓存时间 echo TIME-$a;
			if(TIME - $a > CacheTime){
				$this->run();
				$this->write_cache($this->template, $this->tpl);
				@chmod($this->cache_ROOT.$this->tpl.".cache.php", 0777);
			}
		}
		return $this->cache_ROOT.$this->tpl.".cache.php";	
	}
	
	function run(){
		$this->inc();
		$this->parse_my();
		$this->parse_sys();
		$this->parse_com();
		$this->parse_sql();
		$this->parse_cache();
		$this->parse_if();
		$this->parse_echo();
		//if(!is_dir(Webroot."cache/")){mkdir(Webroot."cache/",0777,true);}
		//if(!is_dir(Webroot."cache/cms")){mkdir(Webroot."cache/cms",0777,true);}	
	}
	// 主要执行PHP代码
	function parse_cache(){
		$Pattern='/<{(.+?)}>/';
		$this->template = preg_replace('/<{(.+?)}>/',"<?php echo \\1; ?>",$this->template);
	}
	
	function load($tpl){ // 载入模板		
		$this->tpl = $tpl;
		$content = @file_get_contents($this->tpl_ROOT.$this->tpl.'.tpl.php');
		if($content === false) $this->template = "$this->tpl is not exists!";
		else $this->template = $content;                
		return $this->parse();
	}
	//检测模版是否存在
	function template_exist($tpl){	
		$d = is_file($this->tpl_ROOT.$tpl.'.tpl.php');
		if($d === false) return false;
		else return true;
	}
	
	private function write_cache($content, $cachefile = ''){
            if(dmkdir($this->cache_ROOT.dirname($cachefile))){
                if($_GET['debug']){
                    var_dump(fopen($this->cache_ROOT.$cachefile.'.cache.php', 'w'));
                }
                if(@$fp = fopen($this->cache_ROOT.$cachefile.'.cache.php', 'w')) {
                        //异常处理
                    flock($fp, 2);
                    fwrite($fp, $content);
                    fclose($fp);
                }
                
            }
	}
	
	//e地址规则
	function url($e=array()){
		if(!$this->template) return false;
		foreach($e as $v){
			$url = explode('|',$v); //$v 结构 替换后地址|执行文件|参数1：参数2：参数3...	
			if(count($url)===2){
				$preg = "/".$v[1];
				preg_replace($v[1]);
			}
		}
	}
}
?>